#include "com_gamerole_opencv_MainActivity.h"
#include "Convert.h"
#include <android/bitmap.h>
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
Mat originTemp;

void test1(Mat src);

void testBlur(Mat temp);

void testBlurGaosi(Mat temp);

void testBlurGaosiShuangbian(Mat temp);

void kernel(Mat temp);
void bianyuan(Mat temp);

Mat init(JNIEnv *env, jobject bitmap) {
    AndroidBitmapInfo info;
    void *pixels;

    CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
    CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
              info.format == ANDROID_BITMAP_FORMAT_RGB_565);
    CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
    CV_Assert(pixels);
    Mat temp1;
    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
        originTemp = Mat(info.height, info.width, CV_8UC4, pixels);
        temp1 = Mat(info.height, info.width, CV_8UC3);
        cvtColor(originTemp, temp1, COLOR_BGRA2BGR);
    }
    return temp1;
}

void change(Mat src, Mat dst) {
    Mat temp(src.rows, src.cols, CV_8UC3);
    cvtColor(dst, temp, COLOR_BGR2RGB);
    cvtColor(temp, src, COLOR_RGB2BGR);
    cvtColor(src, originTemp, COLOR_BGR2BGRA);

}

extern "C" JNIEXPORT void
JNICALL Java_com_gamerole_opencv_MainActivity_getEdge(
        JNIEnv *env, jobject obj, jobject bitmap) {
    const Mat &src = init(env, bitmap);
    test1(src);
    AndroidBitmap_unlockPixels(env, bitmap);
}

extern "C" JNIEXPORT void
JNICALL Java_com_gamerole_opencv_MainActivity_blur(JNIEnv *env, jobject thiz, jobject bitmap) {
    const Mat &src = init(env, bitmap);
    testBlur(src);
    AndroidBitmap_unlockPixels(env, bitmap);
}
extern "C" JNIEXPORT void
JNICALL Java_com_gamerole_opencv_MainActivity_blurGaosi(JNIEnv *env, jobject thiz, jobject bitmap) {
    const Mat &src = init(env, bitmap);
    testBlurGaosi(src);
    AndroidBitmap_unlockPixels(env, bitmap);
}
extern "C" JNIEXPORT void
JNICALL Java_com_gamerole_opencv_MainActivity_blurGaosiShuangbian(JNIEnv *env, jobject thiz,
                                                                  jobject bitmap) {
    const Mat &src = init(env, bitmap);
    testBlurGaosiShuangbian(src);
    AndroidBitmap_unlockPixels(env, bitmap);
}
extern "C" JNIEXPORT void
JNICALL Java_com_gamerole_opencv_MainActivity_kernel(JNIEnv *env, jobject thiz,
                                                     jobject bitmap) {
    const Mat &src = init(env, bitmap);
    kernel(src);
    AndroidBitmap_unlockPixels(env, bitmap);
}
extern "C" JNIEXPORT void
JNICALL Java_com_gamerole_opencv_MainActivity_bianyuan(JNIEnv *env, jobject thiz,
                                                     jobject bitmap) {
    const Mat &src = init(env, bitmap);
    bianyuan(src);
    AndroidBitmap_unlockPixels(env, bitmap);
}
void test1(Mat src) {
    int width = src.cols;
    int height = src.rows;
    Mat dst(src.size(), CV_8UC3);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int b = src.at<Vec4i>(i, j)[0];
            int g = src.at<Vec4i>(i, j)[1];
            int r = src.at<Vec4i>(i, j)[2];
            dst.at<Vec4i>(i, j)[0] = MIN(r, MIN(g, b));
            dst.at<Vec4i>(i, j)[1] = MIN(r, MIN(g, b));
            dst.at<Vec4i>(i, j)[2] = MIN(r, MIN(g, b));
        }
    }

    change(src, dst);
}

void testBlur(Mat src) {
    Mat dst(src.rows, src.cols, CV_8UC3);
    blur(src, dst, Size(11, 11), Point(-1, -1));
    change(src, dst);
}

void testBlurGaosi(Mat src) {
    Mat dst(src.rows, src.cols, CV_8UC3);
    GaussianBlur(src, dst, Size(11, 11), 11, 11);
    change(src, dst);
}

/**
 * 高斯双边滤波
 */
void testBlurGaosiShuangbian(Mat src) {
    Mat dst(src.rows, src.cols, CV_8UC3);
    bilateralFilter(src, dst, 15, 150, 3);
    change(src, dst);
}

/**
 * 算子
 */
void kernel(Mat src) {
    Mat dst(src.rows, src.cols, CV_8UC3);
    Mat kernel = (Mat_<int>(3, 3)
            <<
            -1, 0, -1,
            0, 5, 0,
            -1, 0, -1);
    filter2D(src, dst, -1, kernel, Point(-1, -1));
//    bilateralFilter(src, dst, 15, 150, 3);
    change(src, dst);
}
/**
 * 边缘提取
 * Sobel -1,0,1   -1,-2,-1
 *       -2,0,2   0, 0, 0
 *       -1,0,1   1, 2, 1
 * Scharr -3,0,3   -3,-10,-3
 *        -10,0,10   0, 0, 0
 *        -3,0,3   3, 10, 3
 */
void bianyuan(Mat src) {
    Mat dst;
    Mat blur,gray;
    GaussianBlur(src,blur,Size(3,3),0,0);
    cvtColor(blur,gray,COLOR_BGR2GRAY);
    Mat xgrad,ygrad;
    Sobel(gray,xgrad,CV_16S,1,0,3);
    Sobel(gray,ygrad,CV_16S,0,1,3);
    convertScaleAbs(xgrad,xgrad);
    convertScaleAbs(ygrad,ygrad);
    addWeighted(xgrad,0.5,ygrad,0.5,0,dst);
    cvtColor(dst,dst,COLOR_GRAY2BGR);

    change(src, dst);
}